package school.web;

import java.util.ArrayList;
import java.util.Iterator;

import org.springframework.security.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import school.domain.Course;
import school.domain.Customer;
import school.domain.Group;
import school.domain.Lesson;
import school.domain.Staff;
import school.domain.TheoryLesson;
import school.repository.CourseDao;
import school.repository.GroupDao;
import school.repository.LessonDao;
import school.repository.StaffDao;
import school.repository.TheoryLessonDao;

import com.ibm.db2.jcc.a.SqlException;

@Controller
public class CustomerController {
	
	private CourseDao courseDao;
	private GroupDao groupDao;
	private StaffDao staffDao;
	private Customer customer;
	private LessonDao lessonDao;
	private TheoryLessonDao theoryLessonDao;
	
	@RequestMapping("/customer/staff.htm")
	public String handleInstructors() {
		return "customer/instructors";
	}
	
	@RequestMapping("/customer/choose-instructor.htm")
	public String handleChooseInstructor(ModelMap map,
										@RequestParam("gid") int groupId,
										@RequestParam("enrollTo") String courseType)
	{
		ArrayList<Staff> staff = new ArrayList<Staff>();
		ArrayList<String> categories = new ArrayList<String>();
		System.out.println("CustomerController,choose.htm "+courseType);
		
		try {
			staff = staffDao.getWholeStaff();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if(courseType.compareTo("ride")==0) {
			try {
				categories = courseDao.getCategories();
				System.out.println("CustomerController,choose.htm "+categories.get(0));
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("CustomerController,choose.htm "+courseType);
		}
		
		if(courseType.compareTo("ride")==0) {
			map.addAttribute("categories", categories);
			System.out.println("CustomerController,choose.htm "+categories.get(0));
		}
		
		map.addAttribute("groupId", groupId);
		map.addAttribute("staff", staff);
		map.addAttribute("enrollTo", courseType);
		
		return "/customer/choose";
	}
	
	@RequestMapping(value = "/customer/available-courses.htm", method = RequestMethod.POST)
	public String handleJoinGroup(ModelMap map,
								@RequestParam("gid") int groupId,
								@RequestParam("sid") int staffId,
								@RequestParam("catId") int catId) {		
		try {
			catId++;
			System.out.println("CustomerController,POST a...-courses.htm "+catId);
			courseDao.enroll(groupId, customer.getId(), staffId, catId);
		
		} catch (SqlException e) {
			if(e.getSQLState().contentEquals("75006")) {
				map.addAttribute("errorMessage", "Nie można zapisać.");
				map.addAttribute("returnLink", "courses.htm");
				return "/customer/error";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		try {
			ArrayList<Group> groups = groupDao.getAvailable(customer.getId());
			ArrayList<Course> courses = courseDao.getByCustomerId(customer.getId());
			ArrayList<Lesson> lessons = lessonDao.getAvailableForCustomer(customer.getId());
			
			map.addAttribute("groups", groups);
			map.addAttribute("courses", courses);
			map.addAttribute("lessons", lessons);
			
		} catch (SqlException e) {
			System.out.println(e.getSQLState() + "," + e.getErrorCode());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "customer/courses";
	}
	
	@RequestMapping("/customer/payment.htm")
	public String handlePayment() {
		
		return "customer/payment";
	}
	
	@RequestMapping("/customer/lessons.htm")
	public String handleLessons(ModelMap map, 
								@RequestParam("cid") int courseIdentifier) {
		try {
			ArrayList<Lesson> lessons = lessonDao.getByCourseId(courseIdentifier);
			
			String category = lessons.get(0).getCategory();
			String instructor = lessons.get(0).getStaffName();			
			
			map.addAttribute("lessonsEmpty", "false");
			map.addAttribute("lessons", lessons);
			map.addAttribute("category", category);
			map.addAttribute("instructor", instructor);
			
		} catch (IndexOutOfBoundsException e) {
			System.out.println("No lessons to display.");
			map.addAttribute("lessonsEmpty", "true");
		} catch (SqlException e) {
			System.out.println(e.getSQLState() + "," + e.getErrorCode());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "customer/lessons";
	}
	
	@RequestMapping(value = "/customer/schedule.htm")
	public String handleSchedule(ModelMap map, 
								@RequestParam("gid") int groupId) {
		try {
			ArrayList<TheoryLesson> theoryLessons = theoryLessonDao.getByGroupId(groupId);			
			Group group = groupDao.getByGroupId(groupId);
			String category = group.getCategoryName();
			String instructor = group.getStaffName();
			
			map.addAttribute("theoryLessons", theoryLessons);
			map.addAttribute("category", category);
			map.addAttribute("instructor", instructor);
			
		} catch (SqlException e) {
			System.out.println(e.getSQLState() + "," + e.getErrorCode());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "customer/schedule";
	}
	
	@RequestMapping(value = "/customer/dropout.htm", method = RequestMethod.POST)
	public String handleDropOut(ModelMap map, 
								@RequestParam("courseIdentifier") int courseIdentifier) {
		try {
			courseDao.dropOutFromCourse(courseIdentifier, customer.getId());
		} catch (SqlException e) {
			if(e.getSQLState().contentEquals("75004")) {
				map.addAttribute("errorMessage", "Nie można wypisać z kursu.");
				map.addAttribute("returnLink", "mycourses.htm");
				return "customer/error";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println("id: "+courseIdentifier);
		return "redirect:mycourses.htm";
	}
	
	@RequestMapping(value = "/customer/cancel.htm", method = RequestMethod.POST)
	public String handleCancel(ModelMap map, 
								@RequestParam("lessonIdentifier") int lessonIdentifier,
								@RequestParam("courseIdentifier") int courseIdentifier) {
		
		String redirectLink = "redirect:lessons.htm?cid="+courseIdentifier;
		
		try {
			lessonDao.cancelLesson(lessonIdentifier, customer.getId());
		} catch (SqlException e) {
			if(e.getSQLState().contentEquals("75005")) {
				map.addAttribute("errorMessage", "Nie można odwołać lekcji.");
				map.addAttribute("returnLink", redirectLink);
				return "customer/error";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return redirectLink;
	}
	
	@RequestMapping(value = "/customer/mycourses.htm", method = RequestMethod.GET)
	public String handleMyCourses(ModelMap map) {
		customer = (Customer)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		int groupId=0;
		System.out.println("CustomerController,mycourses.htm: "+customer.getUsername());
		
		try {
			ArrayList<Course> courses = courseDao.getByCustomerId(customer.getId());
			ArrayList<String> instructors = new ArrayList<String>();
			ArrayList<Course> ridingCourses = new ArrayList<Course>();
			
			Iterator<Course> iterator = courses.iterator();
			while(iterator.hasNext()) {
				Course course = (Course)iterator.next();
				groupId = course.getGroupId();
				if(groupId==0) {
					ridingCourses.add(course);
					iterator.remove();
				}
				else {
					Group group = groupDao.getByGroupId(groupId);
					instructors.add(group.getStaffName());
				}
			}
			
			map.addAttribute("fullCourses", courses);
			map.addAttribute("ridingCourses", ridingCourses);
			map.addAttribute("instructors", instructors);
			
		} catch (SqlException e) {
			System.out.println(e.getSQLState() + "," + e.getErrorCode());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "customer/mycourses";
	}
	
	@RequestMapping(value = "/customer/mycourses.htm", method = RequestMethod.POST)
	public String handleMyCoursesWithOrder(ModelMap map) {
		customer = (Customer)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		int groupId=0;
		System.out.println("CustomerController,mycourses.htm: "+customer.getUsername());
		
		try {
			ArrayList<Course> courses = courseDao.getByCustomerIdOrderByStaffName(customer.getId());
			
			ArrayList<String> instructors = new ArrayList<String>();
			ArrayList<Course> ridingCourses = new ArrayList<Course>();
			
			Iterator<Course> iterator = courses.iterator();
			
			while(iterator.hasNext()) {
				
				Course course = (Course)iterator.next();
				groupId = course.getGroupId();
				
				if(groupId==0) {
					ridingCourses.add(course);
					iterator.remove();
				}
				else {
					Group group = groupDao.getByGroupId(groupId);
					instructors.add(group.getStaffName());
				}
			}
			
			map.addAttribute("fullCourses", courses);
			map.addAttribute("ridingCourses", ridingCourses);
			map.addAttribute("instructors", instructors);
			
		} catch (SqlException e) {
			System.out.println(e.getSQLState() + "," + e.getErrorCode());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "customer/mycourses";
	}
	
	@RequestMapping(value = "/customer/available-courses.htm", method = RequestMethod.GET)
	public String handleCourses(ModelMap map) {
		
		try {
			ArrayList<Group> groups = groupDao.getAvailable(customer.getId());
			ArrayList<Course> courses = courseDao.getByCustomerId(customer.getId());
			ArrayList<Lesson> lessons = lessonDao.getAvailableForCustomer(customer.getId());
			
			map.addAttribute("groups", groups);
			map.addAttribute("courses", courses);
			map.addAttribute("lessons", lessons);
			
		} catch (SqlException e) {
			System.out.println(e.getSQLState() + "," + e.getErrorCode());
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "customer/courses";
	}

	public CourseDao getCourseDao() {
		return courseDao;
	}

	public void setCourseDao(CourseDao courseDao) {
		this.courseDao = courseDao;
	}

	public GroupDao getGroupDao() {
		return groupDao;
	}

	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}

	public StaffDao getStaffDao() {
		return staffDao;
	}

	public void setStaffDao(StaffDao staffDao) {
		this.staffDao = staffDao;
	}

	public LessonDao getLessonDao() {
		return lessonDao;
	}

	public void setLessonDao(LessonDao lessonDao) {
		this.lessonDao = lessonDao;
	}
	
	public TheoryLessonDao getTheoryLessonDao() {
		return theoryLessonDao;
	}

	public void setTheoryLessonDao(TheoryLessonDao theoryLessonDao) {
		this.theoryLessonDao = theoryLessonDao;
	}
}
